package validator.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import validator.annotation.Validate;
import validator.exception.ValidateException;
import validator.handle.Validator;

public class ValidatorUtil {
	public static void validate(Object obj) {
		if (obj == null || !obj.getClass().isAnnotationPresent(Validate.class))
			return;

		Field[] fields = obj.getClass().getDeclaredFields();
		for (Field f : fields) {
			validate(f, obj);
		}
	}

	public static void validate(Field f, Object obj) {
		Object v = getFieldValue(f, obj);
		if (v != null) {
			validate(v);
		}

		validate(f.getAnnotations(), f, v);
	}

	private static void validate(Annotation[] annotations, Field f, Object v) {
		for (Annotation anno : annotations) {
			Class<? extends Annotation> clazz = anno.annotationType();
			if (!clazz.isAnnotationPresent(Validate.class))
				continue;

			try {
				validate(clazz.getAnnotations(), f, v);
			} catch (ValidateException e) {
				throw new ValidateException(value(anno), e);
			}

			Validator validator = AnnotationFactory.getValidator(clazz);
			if (validator != null && validator.isValid(f.getType())) {
				validator.validate(anno, v);
			}
		}
	}

	private static String value(Annotation anno) {
		try {
			return (String) anno.annotationType().getMethod("value").invoke(anno);
		} catch (Exception e) {
			return null;
		}
	}

	private static Object getFieldValue(Field f, Object obj) {
		try {
			f.setAccessible(true);
			return f.get(obj);
		} catch (Exception e) {
			throw new ValidateException(e);
		}
	}
}
